\documentclass[12pt]{article}
\usepackage{geometry}
\geometry{margin=1.5cm, vmargin={0pt,1cm}}
\setlength{\topmargin}{-1cm}
\setlength{\paperheight}{29.7cm}
\setlength{\textheight}{25.3cm}

% useful packages.
\usepackage{ctex}
\usepackage{amsfonts}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{amsthm}
\usepackage{enumerate}
\usepackage{graphicx}
\usepackage{multicol}
\usepackage{multirow}
\usepackage{fancyhdr}
\usepackage{layout}
\usepackage{setspace}
\usepackage{float}
\usepackage[table,xcdraw]{xcolor}

% some common command
\newcommand{\dif}{\mathrm{d}}
\newcommand{\avg}[1]{\left\langle #1 \right\rangle}
\newcommand{\difFrac}[2]{\frac{\dif #1}{\dif #2}}
\newcommand{\pdfFrac}[2]{\frac{\partial #1}{\partial #2}}
\newcommand{\OFL}{\mathrm{OFL}}
\newcommand{\UFL}{\mathrm{UFL}}
\newcommand{\fl}{\mathrm{fl}}
\newcommand{\op}{\odot}
\newcommand{\Eabs}{E_{\mathrm{abs}}}
\newcommand{\Erel}{E_{\mathrm{rel}}}

\large
\begin{document}
\pagestyle{fancy}
\fancyhead{}
\lhead{Chen JiaRui}
\chead{Numerical Solutions of Differential Equations - Project \#2}
\rhead{2021.06.08}

\title{Project \#2 - Design Doucument}
\author{陈嘉锐  3180101998}
\maketitle

\begin{spacing}{1.5}

%
%\subsection{Error and runtime with different steps}
%\begin{figure}[htbp]
%	\centering
%	\includegraphics[scale=0.5]{./images/different_steps/IVP1_error_with_different_method.png}
%	\hspace{1in}
%	\includegraphics[scale=0.5]{./images/different_steps/IVP1_runtime_with_different_method.png}
%	\caption{different method}
%\end{figure}


\section{矩阵和向量}
本次作业将 std::valarray<double> 作为向量使用。
\begin{figure}[htbp]
	\centering
	\includegraphics[scale=0.5]{../figures/Equation.png}
\end{figure}

\subsection{一维情形}
首先一个基类 $SymmetricTridiagonal$ 代表对称三对角矩阵，派生类 $PossionMatrix$ 代表泊松方程对应的系数矩阵，其实就是固定了元素值的对称三对角阵。重载它们的乘法运算符，只需存储主对角线和次对角线元素值，而不用存储整个矩阵。\\
\indent\setlength{\parindent}{1em} $Au=f$的右端项 f 用类 RHS 表示。给定一个 n 和右端项对应的函数 f ，以及边值条件，就能生成对应的向量。最后是一个带权重的 Jacobi 迭代，其中$\omega$ 默认为 $\frac 2 3$ 。

\subsection{二维情形}
二维情形思路和一维时一样，需要注意两点：
\begin{itemize}
  \item [1)] 
  矩阵乘法。系数矩阵 A 虽然不是严格的对称三对角矩阵，但是可以分块为对称三对角矩阵，主对角线上每一块又是对称三对角矩阵，就可以利用一维的情形。这时矩阵乘法分块最后再组装起来。
  \item [2)]
  右端项 f 的边值问题。需要遍历，找到那些被边值影响到的点，把边值施加上去，这里涉及到编号的问题，需要实现构建一个编号与坐标的一一映射。
\end{itemize}

\section{限制算子与插值算子}
\begin{figure}[htbp]
	\centering
	\includegraphics[scale=0.5]{../figures/Operator.png}
\end{figure}

这些算子都是模板类，模板参数为维度 DIM = 1 或 2。限制算子和插值算子各有一个抽象基类，具体的限制方法和插值方法在派生类中实现。这里注意到需要 quadratic 插值算子，可以用二次插值方法（需要三个点）推导出其对应系数。同样的，我们并不需要明确写出其矩阵，只需重载其乘法运算符即可。

\section{Cycle 和 多重网格}
\begin{figure}[htbp]
	\centering
	\includegraphics[scale=0.5]{../figures/Multigrid.png}
\end{figure}

\subsection{Cycle}
这里先有一个模板类 $VCycle$，有3个模板参数，分别是维度，限制算子和插值算子，主要实现了讲义中的 VC 方法，注意 $v_1$ 和 $v_2$ 默认为2。\\
\indent\setlength{\parindent}{1em}然后是派生类 $FullMultigridVCycle$ 继承自 $VCycle$，同样是模板类，同样的模板参数，拥有与基类同名的虚函数 Solve() 用以求解。

\subsection{Multigrid}
紧接着是多重网格类 $Multigrid$，也是模板类，模板参数分别为维度，Cycle，限制算子，插值算子，实现个性化定制。求解时调用对应的 Cycle 求解函数即可。\\
\indent\setlength{\parindent}{1em}最后值得一提的是这里多定义了一个看起来没有用的抽象类 $AbstractMultigrid$ 作为 $Multigrid$ 的父类，是为了辅助工厂模式，具体利用到了多态的原理。

\section{Factory 和 Singleton}
\begin{figure}[htbp]
	\centering
	\includegraphics[scale=0.5]{../figures/SingletonFactory.png}
\end{figure}
这里使用到了上次project中已经实现的 Factory 和 Singleton 技术，也就是抽象出一个对象工厂，我从文件里把要生成的对象名（对象参数）读进来，生成对应的产品。同时采用模板类 SingletonHolder 保证整个过程中我只有一个这样的对象工厂。生成产品时调用对应的 Create() 函数即可，不过需要实现将这些函数注册好。值得一提的是，这里的 CreateMultigrid() 函数返回值是\\ $std::shared\_ptr<AbstractMultigrid>$ ，采用智能指针防止用户忘记 delete，返回的是抽象基类 AbstractMultigrid 的指针，使用时就可以利用多态调用派生类 Multigrid 的成员函数。

\section{main函数}
最后在 main 函数里读入文件中所有组合，生成对应对象，求解方程，并将结果输出到 data/ 目录下对应 txt 文件中。这里默认求解的一维方程和二维方程都是要求中给出的两个非齐次边值方程。为了加速，这里使用了简单的多线程，注意由于工厂采用了单例模式，所以需要给 MultigridFactory 加锁。由于多线程输出会比较混乱，所以这里不再将结果打印到屏幕上，直接输出到文件里。文件以“DIM\_n\_Cycle\_Restriction\_Interpolation.txt” 的格式命名。

\end{spacing}
\end{document}

%%% Local Variables: 
%%% mode: latex
%%% TeX-master: t
%%% End: 
